﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Objects;
using System.Linq;
using System.Linq.Expressions;
using Commons;
using DAL;
using SimpComm;
using log4net;
using System.Linq.Dynamic;

namespace Bll
{
    public class BaseEFDal<T> where T : class
    {
        //申明log变量
        private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        #region 查询普通实现方案(基于Lambda表达式的Where查询)

        /// <summary>
        /// 获取所有Entity
        /// </summary>
        /// <param name="exp">Lambda条件的where</param>
        /// <returns></returns>
        public virtual IEnumerable<T> GetEntities(Func<T, bool> exp)
        {
            using (var Entities = new PizzaDataDataContext())
            {
                return Entities.GetTable<T>().Where(exp).ToList();
            }
        }

        /// <summary>
        /// 计算总个数(分页)
        /// </summary>
        /// <param name="exp">Lambda条件的where</param>
        /// <returns></returns>
        public virtual int GetEntitiesCount(Func<T, bool> exp)
        {
            using (var Entities = new PizzaDataDataContext())
            {
                return Entities.GetTable<T>().Where(exp).Count();
            }
        }

        /// <summary>
        /// 分页查询(Linq分页方式)
        /// </summary>
        /// <param name="pageNumber">当前页</param>
        /// <param name="pageSize">页码</param>
        /// <param name="orderName">lambda排序名称</param>
        /// <param name="sortOrder">排序(升序or降序)</param>
        /// <param name="exp">lambda查询条件where</param>
        /// <returns></returns>
        public virtual IEnumerable<T> GetEntitiesForPaging(int pageNumber, int pageSize, Func<T, string> orderName,
                                                           string sortOrder, Func<T, bool> exp)
        {
            using (var Entities = new PizzaDataDataContext())
            {
                if (sortOrder == "asc") //升序排列
                {
                    return
                        Entities.GetTable<T>().Where(exp).OrderBy(orderName).Skip((pageNumber - 1) * pageSize).Take
                            (pageSize).ToList();
                }
                else
                    return
                        Entities.GetTable<T>().Where(exp).OrderByDescending(orderName).Skip((pageNumber - 1) *
                                                                                                   pageSize).Take(
                                                                                                       pageSize).ToList();
            }
        }

        #region 单条

        /// <summary>
        /// 根据条件查找
        /// </summary>
        /// <param name="exp">lambda查询条件where</param>
        /// <returns></returns>
        public virtual T GetEntity(Func<T, bool> exp)
        {
            using (var Entities = new PizzaDataDataContext())
            {
                return Entities.GetTable<T>().Where(exp).SingleOrDefault();
            }
        }

        /// <summary>
        /// 根据条件查找第一条
        /// </summary>
        /// <param name="exp">lambda查询条件where</param>
        /// <returns></returns>
        public virtual T GetFirstEntity(Func<T, bool> exp, DynamicOrderby dynamicOrderby)
        {
            using (var Entities = new PizzaDataDataContext())
            {
                if (dynamicOrderby != null && dynamicOrderby.IsRight)
                {
                    return
                        Entities.GetTable<T>().Where(exp).AsQueryable().OrderBy(dynamicOrderby.ToString()).
                            FirstOrDefault();
                }
                else
                {
                    return Entities.GetTable<T>().Where(exp).FirstOrDefault();
                }
            }
        }

        public TModel GetModel<TModel>(Func<T, bool> exp, Func<T, TModel> select)
        {
            using (var Entities = new PizzaDataDataContext())
            {
                return Entities.GetTable<T>().Where(exp).Select(select).SingleOrDefault();
            }
        }

        public TModel GetFirstModel<TModel>(Func<T, bool> exp, Func<T, TModel> select, DynamicOrderby dynamicOrderby = null)
        {
            using (var Entities = new PizzaDataDataContext())
            {
                if (dynamicOrderby != null && dynamicOrderby.IsRight)
                {
                    return Entities.GetTable<T>().Where(exp).AsQueryable().OrderBy(dynamicOrderby.ToString()).Select(select).FirstOrDefault();
                }
                else
                {
                    return Entities.GetTable<T>().Where(exp).AsQueryable().Select(select).FirstOrDefault();
                }
            }
        }
        #endregion


        /// <saaummary>
        /// 根据条件查找
        /// </summary>
        /// <param name="exp">lambda查询条件where</param>
        /// <returns></returns>
        public virtual bool Any(Func<T, bool> exp)
        {
            using (var Entities = new PizzaDataDataContext())
            {
                return Entities.GetTable<T>().Where(exp).Any();
            }
        }
        #endregion

        #region 查询Entity To Sql语句外接接口的查询实现

        /// <summary>
        /// 获取所有Entity(立即执行请使用ToList()
        /// </summary>
        /// <param name="commandText">Sql语句</param>
        /// <param name="objParams">可变参数</param>
        /// <returns></returns>
        public virtual IEnumerable<T> GetEntities(string commandText)
        {
            using (var Entities = new PizzaDataDataContext())
            {
                if (!commandText.IsNullOrEmpty())
                    commandText = " where " + commandText;
                return Entities.ExecuteQuery<T>("select * from " + typeof(T).Name + commandText).ToList();
            }
        }

        /// <summary>
        /// 计算总个数(分页)
        /// </summary>
        /// <param name="tableName">表名</param>
        /// <param name="commandText">>Sql where语句</param>
        /// <returns></returns>
        public virtual int GetEntitiesCount(string tableName, string commandText)
        {
            using (var Entities = new PizzaDataDataContext())
            {
                if (!commandText.IsNullOrEmpty())
                    commandText = " where " + commandText;
                return Entities.ExecuteQuery<T>("select * from " + tableName + commandText).Count();
            }
        }

        /// <summary>
        /// 计算总个数(分页)
        /// </summary>
        /// <param name="CommandText">Sql语句</param>
        /// <returns></returns>
        public virtual int GetEntitiesCount(string CommandText)
        {
            using (var Entities = new PizzaDataDataContext())
            {
                if (!CommandText.IsNullOrEmpty())
                    CommandText = " where " + CommandText;
                return Entities.ExecuteQuery<T>("select * from " + typeof(T).Name + CommandText).Count();
            }
        }

        /// <summary>
        /// 分页查询(Linq分页方式)
        /// </summary>
        /// <param name="tableName">表名</param>
        /// <param name="pageNumber">当前页</param>
        /// <param name="pageSize">页码</param>
        /// <param name="orderName">lambda排序名称</param>
        /// <param name="sortOrder">排序(升序or降序)</param>
        /// <param name="CommandText">Sql语句</param>
        /// <param name="Count">总个数</param>
        /// <returns></returns>
        public virtual IEnumerable<T> GetEntitiesForPaging(string tableName, int pageNumber, int pageSize,
                                                           string orderName, string sortOrder, string CommandText,
                                                           out int Count)
        {
            var pager = new PaginationHelper(tableName, orderName, pageSize, pageNumber, sortOrder, CommandText);
            using (var Entities = new PizzaDataDataContext())
            {
                Count = GetEntitiesCount(tableName, CommandText);
                return Entities.ExecuteQuery<T>(pager.GetSelectTopByMaxOrMinPagination()).ToList();
            }
        }

        /// <summary>
        /// 根据条件查找
        /// </summary>
        /// <param name="CommandText">Sql语句</param>
        /// <param name="objParams">可变参数</param>
        /// <returns></returns>
        public virtual T GetEntity(string CommandText)
        {
            using (var Entities = new PizzaDataDataContext())
            {
                return
                    Entities.ExecuteQuery<T>("select * from " + typeof(T).Name + " where " + CommandText).
                        SingleOrDefault();
            }
        }

        #endregion

        #region 增删改实现

        /// <summary>
        /// 插入有默认值的Entity
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public virtual MsgBox Insert(T entity, Action<T> defaultValueFun)
        {
            using (var Entities = new PizzaDataDataContext())
            {
                var obj = Entities.GetTable<T>();
                if (defaultValueFun != null)
                    defaultValueFun(entity);
                try
                {
                    obj.InsertOnSubmit(entity);
                    Entities.SubmitChanges();
                    return new MsgBox(true, "添加成功");
                }
                catch (Exception ex)
                {
                    logger.Debug("添加失败", ex);
                    return new MsgBox(false, "添加失败,请联系管理员.");

                }
            }
        }

        /// <summary>
        /// 更新Entity(注意这里使用的傻瓜式更新,可能性能略低)
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>

        public virtual MsgBox Update(Expression<Func<T, bool>> predicate, Expression<Func<T, T>> updater)
        {
            using (var Entities = new PizzaDataDataContext())
            {
                var obj = Entities.GetTable<T>();
                var row = obj.UpdateBatch(predicate, updater);
                if (row > 0)
                    return new MsgBox(true, "更新成功.");
                return new MsgBox(false, "更新失败,请重试一次.");
            }
        }

        /// <summary>
        /// 删除Entity
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public virtual MsgBox Delete(object pk)
        {
            using (var Entities = new PizzaDataDataContext())
            {
                try
                {
                    var obj = Entities.GetTable<T>();
                    var rows = obj.DeleteByPK(pk);
                    if (rows > 0)
                        return new MsgBox(true, "删除成功");
                    return new MsgBox(false, "删除失败,,数据库忙,请稍后再删除");
                }
                catch (Exception ex)
                {
                    logger.Debug("删除失败", ex);
                    return new MsgBox(false, "删除失败,请联系管理员");
                }
            }
        }
        /// <summary>
        /// 删除Entity
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public virtual MsgBox Delete(Expression<Func<T, bool>> filter)
        {
            using (var Entities = new PizzaDataDataContext())
            {
                try
                {
                    var obj = Entities.GetTable<T>();
                    var rows = obj.DeleteBatch(filter);
                    if (rows > 0)
                        return new MsgBox(true, "删除成功");
                    return new MsgBox(false, "删除失败,,数据库忙,请稍后再删除");
                }
                catch (Exception ex)
                {
                    logger.Debug("删除失败", ex);
                    return new MsgBox(false, "删除失败,请联系管理员");
                }
            }
        }

        #endregion

        public MD<Model> SM<Model>(SMP<T, Model> s)
        {
            using (var Entities = new PizzaDataDataContext())
            {
                if (s.page <= 0) s.page = 1;
                var result = new MD<Model>() { PageSize = s.pageSize, PageIndex = s.page };

                IQueryable<T> dataselect = Entities.GetTable<T>();
                if (s.selected != null)
                {
                    dataselect = dataselect.Where(s.selected).AsQueryable();
                }
                result.Count = dataselect.Count();
                //为0退出
                if (result.Count == 0)
                    return result;

                if (s.dynamicOrderby != null && s.dynamicOrderby.IsRight)
                {
                    dataselect = dataselect.OrderBy(s.dynamicOrderby.ToString());
                }

                if (s.pageSize > 0) //为0不分页
                {
                    dataselect = dataselect.Skip((s.page - 1) * s.pageSize).Take(s.pageSize);
                }
                result.Datas = dataselect.Select(s.getmodel).ToList();
                return result;
            }
        }

    }
}
